ディレクトリ配下の全ファイルを更新時刻順にソートして表示する
カレントディレクトリ以下のファイルを、 所属するディレクトリによらず全て時刻ソートして表示したい、 という時がたまにあります。
ls -lRt
のようなコマンドでできそうな気もします (R
は再帰的に、t
は修正時刻ソート)が、 これだと
-rwxr-xr-x 1 user01 staff 1986 Oct 9 17:51 parser-debug.js
-rwxr-xr-x 1 user01 staff 2975 Oct 9 17:51 parser.js
-rwxr-xr-x 1 user01 staff 45566 Oct 9 17:51 toml-parser.js
./@pkgjs:
total 0
drwxr-xr-x 11 user01 staff 352 Dec 3 20:38 parseargs
のような表示になり、ディレクトリを跨いでのソートができていません。 これでは目的を達成できていないので、 全てのファイルに対するソートのやり方について調べました。
コマンド
結果としてこんなコマンドでできました。
find . -type f -exec stat -c '%y %n' {} + | sort
find
の解説
find
でファイルを探した結果をsort
しているだけですので、 ベースとなるのはfind
コマンドです。
find . -type f -exec stat -c '%y %n' {} +
この部分は
- カレントディレクトリ(
.
)以下を再起的に、 - ファイルのみ(
-type f
)を探し、 - それらについてコマンドを実行(
-exec コマンド {} +
) - コマンドは
stat -c '%y %n'
という感じです。
findは-exec コマンド {} +
のように書くことで、 見つけたファイルリストを引数としてコマンドを実行した時の結果を出力にすることができます。 {}
にファイルリストが展開されるイメージです。 +
はファイルリストとしてコマンドに渡すことを表していますので、 これを書かないと見つけたファイルの個数分コマンドが実行されます。
stat
はファイルのメタデータを見るコマンドで、-c '%y %n'
は、
%y
: 最終修正時刻%n
: ファイルパス
だけを表示させるように指定をしています。
このコマンドだけの出力はこんな感じです。
$ find . -type f -exec stat -c '%y %n' {} +
2024-12-03 19:26:37.306999000 +0900 ./axios/lib/helpers/parseHeaders.js
2024-12-03 19:26:37.306999000 +0900 ./axios/index.d.ts
2024-12-03 19:26:37.306999000 +0900 ./axios/SECURITY.md
2024-10-09 17:51:04.226000000 +0900 ./which/LICENSE
2024-10-09 17:51:04.226000000 +0900 ./which/bin/which
2024-10-09 17:51:04.226000000 +0900 ./which/CHANGELOG.md
見ての通り、この表示では時刻が非常に機械的でソート可能な文字列になっています。 なのであとはこれをsort
するだけでOKですね。
ls -l
ではダメか
なぜ同様の方法として
find . -type f -exec ls -l {} +
というやり方もできそうです。 最初私もこのやり方で満足していたのですが、 実はこれだとなかなか難しいパターンがありました。
この結果を見てください。
$ find . -type f -exec ls -l {} +
-rw-r--r-- 1 user01 staff 0 Dec 4 22:11 ./hoge
-rw-r--r-- 1 user01 staff 645 Jan 8 2020 ./sample.json
# 月 日 年or時分
ソートに向かない点が2箇所あります。
- 月がアルファベット表示
- 年or時分という項目がある
- 最終変更が直近の場合は時分
- 最終変更が古い場合は年
前者はロケールを指定することで数字表記に変更することは可能なのですが、 後者は回避する方法がわかりませんでした。
まとめ
カレントディレクトリ以下のファイルをディレクトリまたぎの修正時刻でソートする方法を調べて見ました。 stat
を使った方法や最終修正時刻(mtime)などの概念については、 なんとなく聞いたことがあったものの改めて調べる良い機会になりました。
以上、誰かの参考になれば幸いです。